package com.rndemo.rn.api;

import android.content.ContentValues;
import android.os.Bundle;
import android.os.Parcel;

import com.facebook.react.bridge.Argument;
import com.facebook.react.bridge.BaseJavaModule;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.rndemo.db.JsDB;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;


/**
 * Created by tzj on 2018/5/21.
 */
public class SqliteModule extends BaseJavaModule {

    private HashMap<String,JsDB> mDbMap = new HashMap<>();

    @Override
    public String getName() {
        return getClass().getSimpleName();
    }

    @ReactMethod
    public void open(ReadableMap map,Callback callback){
        Bundle bundle = Argument.toBundle(map);
        if(bundle == null){
            return;
        }
        JsDB jsDb = new JsDB(bundle,callback);
        mDbMap.put(jsDb.dbName(),jsDb);
    }
    @ReactMethod
    public void close(String dbName){
        JsDB remove = mDbMap.remove(dbName);
        if(remove!=null){
            remove.close();
        }
    }

    @ReactMethod
    public void exec(String dbName,String sql,Promise promise){
        try {
            JsDB jsDB = mDbMap.get(dbName);
            if(jsDB==null && promise!=null){
                promise.reject(new RuntimeException("没找到数据库"+dbName));
                return;
            }
            jsDB.getDbHelper().getReadableDatabase().execSQL(sql);
            if(promise!=null){
                promise.resolve(null);
            }
        }catch (Exception e){
            e.printStackTrace();
            if(promise!=null) {
                promise.reject(e);
            }
        }
    }
    @ReactMethod
    public void insert(String dbName,ReadableMap objMap,ReadableMap whereMap,Promise promise){
        try {
            JsDB jsDB = mDbMap.get(dbName);
            if(jsDB==null && promise!=null){
                promise.reject(new RuntimeException("没找到数据库"+dbName));
                return;
            }
            ContentValues values = toValues(objMap);
            Bundle bundle = Argument.toBundle(whereMap);
            ArrayList arrayList1 = new ArrayList();
            String whereSql = getWhereSql(bundle, arrayList1);
            Object[] objs = null;
            if(arrayList1.size()>0){
                objs = new Object[arrayList1.size()];
                arrayList1.toArray(objs);
            }
            int insert = (int) jsDB.insert(values,whereSql, objs);
            if(promise!=null){
                promise.resolve(insert);
            }
        }catch (Exception e){
            e.printStackTrace();
            if(promise!=null) {
                promise.reject(e);
            }
        }
    }
    @ReactMethod
    public void delete(String dbName,ReadableMap whereMap, Promise promise){
        try {
            JsDB jsDB = mDbMap.get(dbName);
            if(jsDB==null && promise!=null){
                promise.reject(new RuntimeException("没找到数据库"+dbName));
                return;
            }
            Bundle bundle = Argument.toBundle(whereMap);
            ArrayList arrayList1 = new ArrayList();
            String whereSql = getWhereSql(bundle, arrayList1);
            String[] objs = null;
            if(arrayList1.size()>0){
                objs = new String[arrayList1.size()];
            }
            for (int i = 0; i < arrayList1.size(); i++) {
                objs[i] = arrayList1.get(i).toString();
            }
            int del = jsDB.delete(whereSql, objs);
            if(promise!=null){
                promise.resolve(del);
            }
        }catch (Exception e){
            e.printStackTrace();
            if(promise!=null) {
                promise.reject(e);
            }
        }
    }
    @ReactMethod
    public void select(String dbName,ReadableMap whereMap,Promise promise){
        try {
            JsDB jsDB = mDbMap.get(dbName);
            if(jsDB==null && promise!=null){
                promise.reject(new RuntimeException("没找到数据库"+dbName));
                return;
            }
            Bundle bundle = Argument.toBundle(whereMap);
            ArrayList arrayList1 = new ArrayList();
            String whereSql = getWhereSql(bundle, arrayList1);
            String[] objs = null;
            if(arrayList1.size()>0){
                objs = new String[arrayList1.size()];
            }
            for (int i = 0; i < arrayList1.size(); i++) {
                objs[i] = arrayList1.get(i).toString();
            }
            List select = jsDB.select(whereSql, objs);
            if(promise!=null){
                promise.resolve(Argument.makeNativeArray(select));
            }
        }catch (Exception e){
            e.printStackTrace();
            if(promise!=null) {
                promise.reject(e);
            }
        }
    }
    @ReactMethod
    public void update(String dbName,ReadableMap objMap,ReadableMap whereMap,Promise promise){
        try {
            JsDB jsDB = mDbMap.get(dbName);
            if(jsDB==null && promise!=null){
                promise.reject(new RuntimeException("没找到数据库"+dbName));
                return;
            }
            ContentValues values = toValues(objMap);
            Bundle bundle = Argument.toBundle(whereMap);
            ArrayList arrayList1 = new ArrayList();
            String whereSql = getWhereSql(bundle, arrayList1);
            String[] objs = null;
            if(arrayList1.size()>0){
                objs = new String[arrayList1.size()];
            }
            for (int i = 0; i < arrayList1.size(); i++) {
                objs[i] = arrayList1.get(i).toString();
            }
            int update = jsDB.update(values,whereSql, objs);
            if(promise!=null){
                promise.resolve(update);
            }
        }catch (Exception e){
            e.printStackTrace();
            if(promise!=null) {
                promise.reject(e);
            }
        }
    }

    /**
     * 转成map
     */
    private ContentValues toValues(ReadableMap map){
        Map mapTemp = Argument.toMap(map);
        Parcel obtain = Parcel.obtain();
        obtain.writeMap(mapTemp);
        obtain.setDataPosition(0);
        ContentValues values = ContentValues.CREATOR.createFromParcel(obtain);
        obtain.recycle();
        return values;
    }

    /**
     * 组装 where
     */
    private String getWhereSql(Bundle bundle,List list){
        StringBuffer where= new StringBuffer();
        list.clear();
        if(bundle!=null){
            Iterator<String> iterator = bundle.keySet().iterator();
            while (iterator.hasNext()){
                if(where.length()>0){
                    where.append(" and ");
                }
                String next = iterator.next();
                where.append(next).append("=?");
                list.add(bundle.get(next));
            }
        }
        if(where.length()<=0){
            return null;
        }else{
            return where.toString();
        }
    }


}
